#! /usr/bin/python

class Symbol:
    def __init__(self, name, type='', provider=''):
        """
        @param name
            Unique name of the symbol, this name will be the key for the symbols
            lookup map
        @param type
            Type of the symbol, particularly useful to resolve conflict between
            symbols (ie weak or common symbols)
        @param provider
            Provider of this symbol
        """
        self.name = name
        self.type = type
        assert len(type) == 1, 'Unsupported type: %s' % type
        self.provider = provider
    
    def json_serialize(self):
        data = {
            'name':self.name,
            'type':self.type,
        }
        if self.provider:
            data['provider'] = self.provider
        return data
    
    def __str__(self):
        return '[%s] %s' % (self.type, self.name)


class Element:
    def __init__(self, name):
        """
        @param name
            Unique name of the element
            To define a hierarchical namespace use a dot notation. e.g.:
                lib.path.name
        """
        self.name = name
        
        # Symbols provided and used by this element file
        self.provided_symbols = {} # <Symbol.name, Symbol> 
        self.used_symbols = {} # <Symbol.name, Symbol>
        
        # Map to store the element dependencies and their strength
        # This map will be filled by the System initialisation
        self.uses_element_symbols = {} # <Element.name: Symbol.name[]>
        
        # Some output format need to reference elements by unique id
        self.uid = None
    
    def __cmp__(self, other):
        return cmp(self.name, other.name)
    
    def json_serialize(self):
        return {
            'name':self.name,
            'provided_symbols': [s.json_serialize() for s in self.provided_symbols.values()],
            'used_symbols': [s.json_serialize() for s in self.used_symbols.values()],
        }
    
    def __str__(self):
        s = '=== %s ===\n' % self.name
        s += '* Provided:\n'
        s += '\n'.join(map(str, self.provided_symbols.values()))
        s += '\n* Used:\n'
        s += '\n'.join(map(str, self.used_symbols.values()))
        return s
